/* ==================================================================   
 * Created [2009-4-27 下午11:32:55] by Jon.King 
 * ==================================================================  
 * TSS 
 * ================================================================== 
 * mailTo:jinpujun@hotmail.com
 * Copyright (c) Jon.King, 2009-2012 
 * ================================================================== 
 */

package com.jinhe.tss.cms.action;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.jinhe.tss.cms.CMSConstants;
import com.jinhe.tss.cms.entity.Article;
import com.jinhe.tss.cms.entity.Attachment;
import com.jinhe.tss.cms.entity.Channel;
import com.jinhe.tss.cms.entity.ChannelArticle;
import com.jinhe.tss.cms.helper.ArticleHelper;
import com.jinhe.tss.cms.helper.ArticleQueryCondition;
import com.jinhe.tss.cms.helper.parser.ArticleGridParser;
import com.jinhe.tss.cms.helper.translator.ChannelCanSelectTranslator;
import com.jinhe.tss.cms.helper.translator.ExcludeSiteNodeTranslator;
import com.jinhe.tss.cms.service.IArticleService;
import com.jinhe.tss.cms.service.IChannelService;
import com.jinhe.tss.cms.workflow.WorkFlow;
import com.jinhe.tss.cms.workflow.WorkFlowManager;
import com.jinhe.tss.cms.workflow.WorkFlowNode.WorkerFlowButton;
import com.jinhe.tss.component.dynproperty.support.IRemotePropertyService;
import com.jinhe.tss.component.support.persistence.pagequery.PageInfo;
import com.jinhe.tss.component.support.web.webwork.PTActionSupport;
import com.jinhe.tss.core.Config;
import com.jinhe.tss.core.cachepool.CacheManager;
import com.jinhe.tss.core.cachepool.IPool;
import com.jinhe.tss.core.exception.BusinessException;
import com.jinhe.tss.core.sso.Environment;
import com.jinhe.tss.core.util.EasyUtils;
import com.jinhe.tss.core.util.XMLDocUtil;
import com.jinhe.tss.core.web.dispaly.grid.GridDataEncoder;
import com.jinhe.tss.core.web.dispaly.tree.LevelTreeParser;
import com.jinhe.tss.core.web.dispaly.tree.TreeEncoder;
import com.jinhe.tss.core.web.dispaly.xform.XFormEncoder;
import com.jinhe.tss.um.permission.PermissionHelper;
 
public class ArticleAction extends PTActionSupport {

	private static final long serialVersionUID = -4529854543499272897L;
    
	private IArticleService articleService;
	private IChannelService channelService;
	private IRemotePropertyService propertyService;
    
    private Article article = new Article();    // 文章信息
    private ArticleQueryCondition condition = new ArticleQueryCondition();  // 相关的文章信息
    
	private Long    articleId;
	private Long    channelId;
    private Long    toArticleId;
    private Long    oldChannelId;
    
    private Integer  copyTo;           // 标记值区分"复制"与"复制到"。 0：复制；1：复制到。
    private Integer  isTop;            // 前台是否置顶的标记
	private String   articleContent;   // 正文内容
	private String   isCommit;         // 判断修改文章的时候是否是保存并提交
    
	private String  attachList;             // 附件列表
	private String  associateArticleIds;	// 相关文章id
	private String  distributeToChannelIds;   // 分发文章
	
	// 分页信息
	private Integer page;
	private String  field;
	private Integer orderType;
    private int     direction;  //-1 向上  1：向下
    
    //流程相关
    private Integer status;         //文章流程状态
    private Integer oldStatus;      //以前的流程状态
    private Integer workflowId;
	
	/**
	 * <p>
	 * 获取栏目下文章列表
	 * </p>
	 * @return
	 */
	public String getChannelArticles() {
        if (channelId == null) 
            throw new BusinessException("栏目id为空！");
        
        String orderBy;
        if(orderType == null || orderType > 0)  {
            orderBy = field;
        } 
        else {
            orderBy = field + " desc ";
        }

        PageInfo pageInfo = articleService.getChannelArticles(channelId, page, orderBy);
        Channel channel = channelService.getChannelById(channelId);

        List<Article> articles = new ArrayList<Article>();
        List<?> list = pageInfo.getItems();
        if ( !EasyUtils.isNullOrEmpty(list) ) {
            for ( Object temp : list ) {
                Article article = ArticleHelper.createArticle((Object[]) temp);
                articles.add(article);
            }
        }
        
		String entityCode = channel.getArticlesInChannelEntityCode();
        String gridTemplate = propertyService.getGridTemplate(entityCode, CMSConstants.GRID_TEMPLATE_CODE);
		GridDataEncoder gEncoder = new GridDataEncoder(articles, XMLDocUtil.dataXml2Doc(gridTemplate), new ArticleGridParser());

        String[] flowSteps = WorkFlowManager.getInstance().getFlowStepStatusAndNames(channel.getWorkflowId());
		gEncoder.getTemplet().setColumnAttribute("status", "editorvalue", flowSteps[0]);
		gEncoder.getTemplet().setColumnAttribute("status", "editortext",  flowSteps[1]);

		return print(new String[]{"ArticleList", "PageList"}, new Object[]{gEncoder, pageInfo});
	} 
	
	/**
	 * 初始化文章新增信息
	 */
	public String initArticleInfo() {
        Channel channel = channelService.getChannelById(channelId);
        String entityCode = channel.getArticlesInChannelEntityCode();
        
		Map<String, String> map = propertyService.getXFormTemplate(entityCode, CMSConstants.XFORM_TEMPLATE_CODE);
        String template = (String) (map.get(CMSConstants.ARTICLE_TEMPLATE_TAB_NAME));
        if(template == null)
            throw new BusinessException("此文章类型没有进行表单布局设置，请先转到动态属性管理页面设置！");
        
        Map<String, Object> initMap = new HashMap<String, Object>();
        initMap.put("articleTypeId", channel.getArticleTypeId());
        initMap.put("isTop", CMSConstants.FALSE);
        initMap.put("author", Environment.getUserName()); // 默认作者为登录者，前台可进行修改
        
        Document doc = XMLDocUtil.dataXml2Doc(template);
        XFormEncoder baseXFormEncoder = new XFormEncoder(XMLDocUtil.dataXml2Doc(template), initMap, false, false);
        if (-1 != (doc.asXML().toString()).indexOf("name=\"hitCount\"")) {
            baseXFormEncoder.setColumnAttribute("hitCount", "editable", "false");
        }
        if (-1 != (doc.asXML().toString()).indexOf("name=\"status\"")) {
            baseXFormEncoder.setColumnAttribute("status", "editable", "false");
        }
        
        Long tempArticleId = System.currentTimeMillis();
        articleService.createChannelArticleRelation(channelId, tempArticleId); // 创建临时文章ID跟栏目关系，预览附件图片时有用（查找站点文件目录）
        
        Map<String, Object> initMap4Upload = new HashMap<String, Object>();	
        initMap4Upload.put("id", tempArticleId);
        initMap4Upload.put("channelId", channelId);
		XFormEncoder uploadXFormEncoder = new XFormEncoder(CMSConstants.XFORM_TEMPLATE_ARTICLEUPLOAD, initMap4Upload);
        
		GridDataEncoder filesGridEncoder = new GridDataEncoder(new ArrayList<Object>(), CMSConstants.TEMPLATE_ATTACHSLIST);
        
		return print(new String[]{"ArticleInfo", "ArticleContent", "AttachsUpload", "AttachsList"}, 
                new Object[]{baseXFormEncoder, "<![CDATA[]]>", uploadXFormEncoder, filesGridEncoder});
	}
    
    /**
     * 获取文章信息
     */
    public String getArticleInfo() { 
        Article article = articleService.getArticleById(articleId);
        article.setChannelId(channelId);
        
        Map<String, String> map = propertyService.getXFormTemplate(article.getEntityCode(), CMSConstants.XFORM_TEMPLATE_CODE);
        String template = (String) (map.get(CMSConstants.ARTICLE_TEMPLATE_TAB_NAME));
        if(template == null)
            throw new BusinessException("此文章类型没有进行表单布局设置，请先转到动态属性管理页面设置！");
        
        Document doc = XMLDocUtil.dataXml2Doc(template);
        XFormEncoder baseXFormEncoder = new XFormEncoder(doc, article, false, false);
        if(-1 != (doc.asXML().toString()).indexOf("name=\"hitCount\""))
            baseXFormEncoder.setColumnAttribute("hitCount", "editable", "false");
        if(-1 != (doc.asXML().toString()).indexOf("name=\"status\""))
            baseXFormEncoder.setColumnAttribute("status", "editable", "false");
        
        XFormEncoder uploadXFormEncoder = new XFormEncoder(CMSConstants.XFORM_TEMPLATE_ARTICLEUPLOAD, article);
        
        List<Attachment> attachments = new ArrayList<Attachment>(article.getAttachments().values());
        GridDataEncoder uploadGridEncoder = new GridDataEncoder(attachments, CMSConstants.TEMPLATE_ATTACHSLIST);
        
        return print(new String[]{"ArticleInfo", "ArticleContent", "AttachsUpload", "AttachsList"}, 
                new Object[]{baseXFormEncoder, "<![CDATA[" + article.getContent() + "]]>", uploadXFormEncoder, uploadGridEncoder});
    }
    
	/**
	 * 保存文章。或者是保存并提交文章。
	 */
	public String saveArticleInfo() {
        if( Config.TRUE.equalsIgnoreCase(isCommit) ){
            article.setStatus(CMSConstants.TOPUBLISH_STATUS);
        }
        
        article.setContent(articleContent);
	    if(article.getId() == null || article.getId().longValue() == 0) {
            //新增的时候上传的附件对象以new Date()为主键，此处的"articleId"就是这个值
	        articleService.createArticle(article, channelId, attachList, articleId); 
	    } 
	    else {
	        articleService.updateArticle(article, channelId, attachList);
	    }
	    return printSuccessMessage();
	}

	/**
	 * 删除文章
	 */
	public String deleteArticle() {
        if (articleId == null) 
            throw new BusinessException("文章id为空！");
        
	    articleService.deleteArticle(articleId, channelId);
	    return printSuccessMessage("删除文章成功");
	}
	
	/**
	 * 移动文章（跨栏目移动）
	 */
	public String moveArticle() {
        if (channelId == null || oldChannelId == null) 
            throw new BusinessException("栏目id为空！");
        if (articleId == null)
            throw new BusinessException("文章id为空！");
        
	    articleService.moveArticle(articleId, oldChannelId, channelId);
        return printSuccessMessage("移动文章成功");
	}
	
	/**
	 * 文章排序
	 */
	public String moveArticleDownOrUp() {
	    articleService.moveArticleDownOrUp(articleId, toArticleId, channelId);
        return printSuccessMessage("文章排序成功");
	}
	
	/**
	 *  跨页的文章排序
	 */
	public String moveArticleDownOrUpCross(){
	    articleService.moveArticleDownOrUpCross(articleId, channelId, page, direction);
        return printSuccessMessage("文章排序（跨页）成功");
	}
    
	/**
	 * 文章锁定
	 */
	public String lockingArticle() {
	    articleService.lockingArticle(articleId);
        return printSuccessMessage("锁定文章成功");
	}
	/**
	 * 文章解锁
	 */
	public String unLockingArticle() {
	    articleService.unLockingArticle(articleId);
        return printSuccessMessage("解除锁定成功");
	}
	/**
	 * 改变文章状态
	 */
	public String changeArticleStatus() {
	    articleService.changeArticleStatus(articleId, oldStatus, status, workflowId);
        return printSuccessMessage("状态改变成功");
	}
    
    /**
     * 获取文章流程信息
     */
    public String getWorkFlowStatus() {
        if (CMSConstants.LOCKING_STATUS.equals(status))
            status = CMSConstants.START_STATUS;
        
        // 当文章的状态为XMLSTATUS时，转换成PUBLISHSTATUS(待发布)状态来处理流程
        if (CMSConstants.XML_STATUS.equals(status))
            status = CMSConstants.TOPUBLISH_STATUS;
        
        Document doc = DocumentHelper.createDocument();
        Element workflowElement = doc.addElement("WorkFlow");
        Element nextButtonElement = workflowElement.addElement("NextButton");
        
        WorkFlowManager wfManager = WorkFlowManager.getInstance();
        
        WorkerFlowButton fb = wfManager.getNextButton(workflowId, status);
        if (fb != null) {
            String operationId = fb.getStatus().toString();
            if (articleService.getArticleWorkflowPermission(operationId, CMSConstants.DEFAULT_WORKFLOW_ID)) {
                Element buttonElement = nextButtonElement.addElement("Button");
                buttonElement.addAttribute("name", fb.getButton());
                buttonElement.addAttribute("id", fb.getStatus().toString());
            }
        }
        
        Map<Integer, WorkerFlowButton> map = wfManager.getPreviews(workflowId, status);
        Element previewButtonElement = workflowElement.addElement("PreviewButton");
        for ( WorkerFlowButton pfb : map.values()) {
            String operationId = "-" + pfb.getStatus(); // 加 - 号表示逆流程
            if (articleService.getArticleWorkflowPermission(operationId, CMSConstants.DEFAULT_WORKFLOW_ID)) {
                Element buttonElement = previewButtonElement.addElement("Button");
                buttonElement.addAttribute("name", pfb.getButton());
                buttonElement.addAttribute("id", pfb.getStatus().toString());
            }
        }
        return print("ArticleWorkFlow", doc.asXML());
    }

	/**
	 *  获取工作流信息
	 */
	public String getWorkFlowTree() {
        List<WorkFlow> list = new ArrayList<WorkFlow>();
        
		IPool pool = CacheManager.getInstance().getCachePool("workflows_info");
		List<?> codeList = WorkFlowManager.getInstance().getWorkFlowCodes();
		for( Object code : codeList ){
			 WorkFlow flow = (WorkFlow) pool.getObject(code).getValue();
			 list.add(flow);
		}
        TreeEncoder encoder = new TreeEncoder(list);
		encoder.setRootCanSelect(false);
	    return print("WorkFlowTree", encoder);
	}
	
	/**
	 * 根据对栏目的权限过滤对文章的权限
	 */
	public String getArticleOperation(){
        PermissionHelper permissionHelper = PermissionHelper.getInstance();
        List<?> operations = permissionHelper.getOperationsByResource(CMSConstants.RESOURCE_TYPE_CHANNEL, channelId, Environment.getOperatorId());
        
        String permissionAll = "p1,p2,";
		for ( Object operation : operations ) {
			permissionAll += "a_" + operation + ",";
		}
        permissionAll += "cd1,cd2,cd3,cd4,cd5,ca1,ca2,ca3,ca4,ca5";
	    return print("Operation", permissionAll);
	}
	
	/**
	 * 文章的复制和复制到
	 */
	public String copyArticle(){
        if (channelId == null) 
            throw new BusinessException("栏目id为空！");
        if (articleId == null) 
            throw new BusinessException("文章id为空！");

	    articleService.copyArticle(articleId, channelId, CMSConstants.TRUE.equals(copyTo));
	    return printSuccessMessage("复制成功");
	}

	/**
	 * 转载文章
	 */
	public String reshipArticle(){
        if (channelId == null)
            throw new BusinessException("栏目id为空！");
        if (articleId == null)
            throw new BusinessException("文章id为空！");
        
	    articleService.reshipArticle(articleId, channelId, oldChannelId);
        return printSuccessMessage("转载成功");
	}
	
	/**
	 *  文章置顶和取消置顶
	 */
	public String doOrUndoTopArticle(){
	    if(CMSConstants.TRUE.equals(isTop)){
	        articleService.undoTopArticle(articleId, channelId);
	        return printSuccessMessage("置顶成功");
	    }
	    
	    articleService.doTopArticle(articleId, channelId);
        return printSuccessMessage("取消置顶成功");
	}
    
	/**
	 *  获得指定文章的关联信息
	 */
	public String getArticleExistRelationship(){
		Object[] data = articleService.getArticleExistRelationship(articleId);
		TreeEncoder treeEncoder = new TreeEncoder(data[0], new LevelTreeParser());
		treeEncoder.setTranslator(new ExcludeSiteNodeTranslator());
        
	    return print( new String[] { "AssociateArticleTree", "AssociateArticleExistTree" }, 
	            new Object[]{ treeEncoder, new TreeEncoder(data[1]) } );
	}
	
	/**
	 *  获得栏目的文章列表以建立起关联关系
	 */
	public String getPageArticlesByChannel() {
	    PageInfo pageInfo = articleService.getChannelArticles(channelId, page);
	    
	    List<Article> articles = new ArrayList<Article>();
	    List<?> list = pageInfo.getItems();
        if ( !EasyUtils.isNullOrEmpty(list) ) {
            for ( Object temp : list ) {
                Article article = ArticleHelper.createArticle((Object[]) temp);
                articles.add(article);
            }
        }
        return print("AssociateArticleList", new TreeEncoder( articles ));
	}
	
	/**
	 * 保存相关文章关系
	 */
	public String relatedArticleTo(){
	    articleService.relatedArticleTo(articleId, associateArticleIds);
        return printSuccessMessage("成功保存文章的关联关系！");
	}
	
	/**
	 *  获得文章分发关系信息
	 */
	public String getDistributeArticleRelationShip(){
	    Object[] objects = articleService.getDistributeArticleRelationShip(articleId, channelId);
 
		TreeEncoder treeEncoder = new TreeEncoder(objects[0], new LevelTreeParser());
		treeEncoder.setTranslator(new ChannelCanSelectTranslator((String) objects[1], channelId));
        treeEncoder.setNeedRootNode(false);
        
		TreeEncoder channelEncoder = new TreeEncoder(objects[2]);
		channelEncoder.setTranslator(new ExcludeSiteNodeTranslator());
        channelEncoder.setRootCanSelect(false);
	    
	    
        return print(new String[]{"distributeArticleTree", "distributeArticleExistTree"}, new Object[]{treeEncoder, channelEncoder});
	}
	
	/**
	 *  保存文章分发关系信息
	 */
	public String saveDistributeArticleRelationShip(){
	    articleService.saveDistributeArticleRelationShip(articleId, channelId, distributeToChannelIds);
        return printSuccessMessage("保存成功");
	}
	
	/**
	 *  获得文章来源信息
	 */
	public String getDistributeArticleSource(){
	    ChannelArticle ca = articleService.getChannelArticle(articleId, channelId);
	    XFormEncoder xEncoder = new XFormEncoder(CMSConstants.XFORM_TEMPLATE_ARTICLE_SOURCE, ca);
		return print("DistributeSource", xEncoder);
	}
	
    /**
     * 获取搜索文章的查询模板
     * @return
     */
    public String getSearchArticleTemplate() {
        XFormEncoder xEncoder = new XFormEncoder(CMSConstants.XFORM_TEMPLATE_SEARCH_ARTICLE);
        return print("SearchArticle", xEncoder);
    }
	/**
	 *  搜索文章列表
	 */
	public String getArticleList() {
	    Object[] data = articleService.searchArticleList(condition);
		GridDataEncoder gEncoder = new GridDataEncoder(data[0], CMSConstants.GRID_TEMPLATE_ARTICLELIST, new ArticleGridParser());
        return print(new String[]{"ArticleList", "PageList"}, new Object[]{gEncoder, (PageInfo)data[1]});
	}	

    public Article getArticle() {
        return article;
    }
    public ArticleQueryCondition getCondition() {
        return condition;
    }
    public void setArticleContent(String articleContent) {
        this.articleContent = articleContent;
    }
    public void setArticleId(Long articleId) {
        this.articleId = articleId;
    }
    public void setAssociateArticleIds(String associateArticleIds) {
        this.associateArticleIds = associateArticleIds;
    }
    public void setAttachList(String attachList) {
        this.attachList = attachList;
    }
    public void setChannelId(Long channelId) {
        this.channelId = channelId;
    }
    public void setCopyTo(Integer copyTo) {
        this.copyTo = copyTo;
    }
    public void setDistributeToChannelIds(String distributeToChannelIds) {
        this.distributeToChannelIds = distributeToChannelIds;
    }
    public void setField(String field) {
        this.field = field;
    }
    public void setIsTop(Integer isTop) {
        this.isTop = isTop;
    }
    public void setToArticleId(Long newArticleId) {
        this.toArticleId = newArticleId;
    }
    public void setOldChannelId(Long oldChannelId) {
        this.oldChannelId = oldChannelId;
    }
    public void setOldStatus(Integer oldStatus) {
        this.oldStatus = oldStatus;
    }
    public void setOrderType(Integer orderType) {
        this.orderType = orderType;
    }
    public void setPage(Integer page) {
        this.page = page;
    }
    public void setStatus(Integer status) {
        this.status = status;
    }
    public void setWorkflowId(Integer workflowId) {
        this.workflowId = workflowId;
    }
    public void setDirection(int direction) {
        this.direction = direction;
    }
    public void setIsCommit(String isCommit) {
        this.isCommit = isCommit;
    }
    
    public void setPropertyService(IRemotePropertyService propertyService) {
        this.propertyService = propertyService;
    }

    public void setService(IArticleService service) {
        this.articleService = service;
    }
    
	public void setChannelService(IChannelService channelService) {
		this.channelService = channelService;
	}
}